#include "SkyNet.h"

static layer config[layer_count] = {
{ "conv0", 320,160,32, 320,160,32, 0,0,0 },  //conv0
{ "conv1", 320,160,32, 320,160,32, 3,1,1 },  //conv1
{ "conv2", 320,160,32, 320,160,64, 1,1,0 },  //conv2
{ "pool1", 320,160,64, 160,80,64,  2,2,0 },  //pool1
{ "conv3", 160,80,64,  160,80,64,  3,1,1 },  //conv3
{ "conv4", 160,80,64,  160,80,96,  1,1,0 },  //conv4
{ "pool2", 160,80,96,  80,40,96,   2,2,0 },  //pool2
{ "conv5", 80,40,96,   80,40,96,   3,1,1 },  //conv5
{ "conv6", 80,40,96,   80,40,192,  1,1,0 },  //conv6
{ "reorg", 80,40,192,  40,20,768,  2,2,0 },  //reorg
{ "pool3", 80,40,192,  40,20,192,  2,2,0 },  //pool3
{ "conv7", 40,20,192,  40,20,192,  3,1,1 },  //conv7
{ "conv8", 40,20,192,  40,20,384,  1,1,0 },  //conv8
{ "conv9", 40,20,384,  40,20,384,  3,1,1 },  //conv9
{ "conv10",40,20,384,  40,20,512,  1,1,0 },  //conv10
{ "cat",   40,20,192,  40,20,1280, 0,0,0 },  //concat
{ "conv11",40,20,1280, 40,20,1280, 3,1,1 },  //conv11
{ "conv12",40,20,1280, 40,20,96,   1,1,0 },  //conv12
{ "conv13",40,20,96,   40,20,32,   1,1,0 },  //conv13
};


int main() {

//*************************************init *********************************
	printf("init SkyNet \n");
	WDT32* parameter;
	WDT32* weight;
	BDT8* biasm;
	BDT8* bbox_blob8;
	BDT* bbox_blob;
	ADT* data[4];
	ADT* data_blob;
	ADT32* data_blob32;
	ADT* fm_blob;
	ADT32* fm_blob32;
	ADT* fm[4];
	BDT* bbox[4];

	for(int p=0; p<4; p++)
	{
		data[p] = (ADT*)sds_alloc(32*160*320*sizeof(ADT));
		fm[p] = (ADT*)sds_alloc(64*160*320*sizeof(ADT));
		bbox[p] = (BDT*)sds_alloc(20*40*16*sizeof(BDT));
	}
	data_blob = (ADT*)sds_alloc(32*323*643*sizeof(ADT));
	parameter = (WDT32*)sds_alloc((441344+6848*4)*sizeof(WDT));
	weight = (WDT32*)sds_alloc(441344*sizeof(WDT));
	biasm = (BDT8*)sds_alloc(6848*sizeof(BDT));
	bbox_blob = (BDT*)sds_alloc(43*83*32*sizeof(BDT));
	fm_blob32 = (ADT32*)sds_alloc(32*fm_all*sizeof(ADT));
	fm_blob = (ADT*)sds_alloc(64*643*323*sizeof(ADT));
	for(int i=0; i<fm_all; i++)
	{
		for(int j=0; j<32; j++)
		{
			#ifdef __APINT__
			fm_blob32[i].range(8*j+7,8*j) = -128;
			#else 
			fm_blob32[i].data[j] = -128;
			#endif
		}
	}
	//*************************************load data *********************************
	printf("load parameter\n");
	load_parameter(parameter, 468736);

	printf("load image\n");
	for (int p = 0; p<4; p++)
		load_fm(data[p], config[0]);

	printf("stitch image\n");
	stitch(data, data_blob, config[0]);

	printf("transform image\n");
	fm_DT_2_DT32(data_blob, &fm_blob32[conv0_offset], config[0]);

	//*************************************HLS, Skynet *********************************
	printf("SkyNet start\n");
	timeval start,end;
	gettimeofday(&start, NULL);
	SkyNet(fm_blob32, parameter);
	gettimeofday(&end, NULL);
	printf("SkyNet costs %luus\n", (end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec);
	//************************************* check the results*********************************
	printf("check SkyNet results \n");

	fm_DT32_2_DT(&fm_blob32[pool1_offset], fm_blob, config[3]);
	distitch(fm_blob, fm, config[3]);
	for (int p = 0; p<4; p++)
	{
		check_fm(fm[p], config[3]);
	}

	fm_DT32_2_DT(&fm_blob32[pool2_offset], fm_blob, config[6]);
	distitch(fm_blob, fm, config[6]);
	for (int p = 0; p<4; p++)
	{
		check_fm(fm[p], config[6]);
	}

	fm_DT32_2_DT(&fm_blob32[conv5_offset], fm_blob, config[7]);
	distitch(fm_blob, fm, config[7]);
	for (int p = 0; p<4; p++)
	{
		check_fm(fm[p], config[7]);
	}

	fm_DT32_2_DT(&fm_blob32[conv6_offset], fm_blob, config[8]);
	distitch(fm_blob, fm, config[8]);
	for (int p = 0; p<4; p++)
	{
		check_fm(fm[p], config[8]);
	}

	fm_DT32_2_DT(&fm_blob32[pool3_offset], fm_blob, config[10]);
	distitch(fm_blob, fm, config[10]);
	for (int p = 0; p<4; p++)
	{
		check_fm(fm[p], config[10]);
	}

	fm_DT32_2_DT(&fm_blob32[conv7_offset], fm_blob, config[11]);
	distitch(fm_blob, fm, config[11]);
	for (int p = 0; p<4; p++)
	{
		check_fm(fm[p], config[11]);
	}

	fm_DT32_2_DT(&fm_blob32[conv8_offset], fm_blob, config[12]);
	distitch(fm_blob, fm, config[12]);
	for (int p = 0; p<4; p++)
	{
		check_fm(fm[p], config[12]);
	}

	fm_DT32_2_DT(&fm_blob32[conv9_offset], fm_blob, config[13]);
	distitch(fm_blob, fm, config[13]);
	for (int p = 0; p<4; p++)
	{
		check_fm(fm[p], config[13]);
	}

	fm_DT32_2_DT(&fm_blob32[conv10_offset], fm_blob, config[14]);
	distitch(fm_blob, fm, config[14]);
	for (int p = 0; p<4; p++)
	{
		check_fm(fm[p], config[14]);
	}

	fm_DT32_2_DT(&fm_blob32[conv11_offset], fm_blob, config[16]);
	distitch(fm_blob, fm, config[16]);
	for (int p = 0; p<4; p++)
	{
		check_fm(fm[p], config[16]);
	}

	fm_DT32_2_DT(&fm_blob32[conv12_offset], fm_blob, config[17]);
	distitch(fm_blob, fm, config[17]);
	for (int p = 0; p<4; p++)
	{
		check_fm(fm[p], config[17]);
	}
#ifdef __APINT__
	bbox_DT8_2_DT(&fm_blob32[conv13_offset], bbox_blob, config[18]);
	distitch_bbox(bbox_blob, bbox, config[18]);
	for (int p = 0; p<4; p++)
	{
		check_bbox(bbox[p], config[18]);
	}
#endif
}
